import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from '../types/index'
import { transformResponseHeader } from '../helpers/header'
import { createError } from '../helpers/error'
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    const { url, data = null, method = 'get', headers, responseType, timeout } = config
    let req = new XMLHttpRequest()
    if (responseType) {
      req.responseType = responseType
    }
    if (timeout) {
      req.timeout = timeout
    }
    req.open(method.toUpperCase(), url!, true)

    req.onreadystatechange = function() {
      if (req.readyState !== XMLHttpRequest.DONE) {
        return
      }
      if (req.readyState === 0) {
        return
      }
      const responseHeaders = transformResponseHeader(req.getAllResponseHeaders())
      const responseData = responseType && responseType !== 'text' ? req.response : req.responseText
      const response: AxiosResponse = {
        data: responseData,
        status: req.status,
        statusText: req.statusText,
        headers: responseHeaders,
        config,
        requset: req
      }
      handleResponse(response)
    }
    req.onerror = function handleError() {
      reject(createError(`Network Error`, config, null, req))
    }
    req.ontimeout = function handleTimeOut() {
      reject(createError(`Timeout of ${timeout} ms exceeded`, config, 'ECONNABORTED', req))
    }
    Object.keys(headers).forEach(name => {
      if (data === null && name.toLowerCase() === 'content-type') {
        delete headers[name]
      } else {
        req.setRequestHeader(name, headers[name])
      }
    })
    req.send(data)

    function handleResponse(response: AxiosResponse): void {
      if (response.status >= 200 && response.status < 300) {
        resolve(response)
      } else {
        reject(
          createError(
            `Request failed with status code ${response.status}`,
            config,
            null,
            req,
            response
          )
        )
      }
    }
  })
}
